package com.youbug.mall.product_pms.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.youbug.common.exception.WrongStatusException;
import com.youbug.mall.product_pms.entity.PmsCategory;
import com.youbug.mall.product_pms.mapper.CategoryMapper;
import com.youbug.mall.product_pms.service.ICategoryService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.youbug.mall.product_pms.vo.Catelog2Vo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;

import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 商品三级分类 服务实现类
 * </p>
 *
 * @author youbug
 * @since 2023-05-07
 */
@Service
public class CategoryServiceImpl extends ServiceImpl<CategoryMapper, PmsCategory> implements ICategoryService {

    private List<PmsCategory> cache;
    @Autowired
    private CategoryMapper categoryMapper;

    @Override
    public List<PmsCategory> listWithTree() {
        if(!CollectionUtils.isEmpty(cache)){
            return cache;
        }
        //1、查询出所有分类
        List<PmsCategory> entities = this.list();
        //2、组装成父子的树形结构
        //2.1)、找到所有一级分类
        List<PmsCategory> levelMenus = entities.stream()
                .filter(e -> e.getParentCid() == 0)
                .peek((menu) -> menu.setChildren(getChildrens(menu, entities)))
                .sorted(Comparator.comparingInt(menu -> (menu.getSort() == null ? 0 : menu.getSort())))
                .collect(Collectors.toList());
        cache = levelMenus;
        return levelMenus;
    }

    @Override
    public boolean deleteById(Long id) {

        PmsCategory category = categoryMapper.hasChildrenById(id);
        if(!ObjectUtils.isEmpty(category)){
            throw new WrongStatusException("含有子种类无法删除");
        }

        boolean remove = this.removeById(id);

        return remove;
    }

    @Override
    public boolean addCategory(PmsCategory category) {

        if(category.getParentCid()==null){
            category.setParentCid(0L);
            category.setCatLevel(1);
            category.setShowStatus(1);
            category.setProductCount(0);
        }
        boolean save = this.save(category);

        return save;
    }

    @CacheEvict(value = "category",allEntries = true)
    @Override
    public void cleanCache(boolean result) {
        if(result){
            this.cache = null;
        }
    }

    @Override
    public Long[] findCatalogPath(Long catalogId) {
        List<Long> paths = new ArrayList<>();
        List<Long> parentPath = findParentPath(catalogId, paths);
        Collections.reverse(parentPath);
        return parentPath.toArray(new Long[parentPath.size()]);
    }
    private List<Long> findParentPath(Long catalogId, List<Long> paths) {
        paths.add(catalogId);
        PmsCategory byId = this.getById(catalogId);
        if(byId.getParentCid()!=0){
            findParentPath(byId.getParentCid(), paths);
        }
        return paths;
    }

    //递归查找所有菜单的子菜单
    private List<PmsCategory> getChildrens(PmsCategory root, List<PmsCategory> all) {

        List<PmsCategory> children = all.stream().filter(category -> {
            return root.getCatId().equals(category.getParentCid());
        }).peek(category -> {
            //1、找到子菜单(递归)
            category.setChildren(getChildrens(category, all));
        }).sorted(Comparator.comparingInt(menu -> (menu.getSort() == null ? 0 : menu.getSort())))
                .collect(Collectors.toList());

        return children;
    }


    @Cacheable(value = {"category"}, key = "#root.method.name",sync = true)
    @Override
    public List<PmsCategory> getLevel1Categorys() {
        System.out.println("getLevel1Categorys........");
        long l = System.currentTimeMillis();
        List<PmsCategory> categories = this.baseMapper.selectList(
                new QueryWrapper<PmsCategory>().eq("parent_cid", 0));
        System.out.println("消耗时间："+ (System.currentTimeMillis() - l));
        return categories;
    }

    @Cacheable(value = "category",key = "#root.methodName")
    @Override
    public Map<String, List<Catelog2Vo>>  getCatalogJson() {
        System.out.println("查询了数据库");

        //将数据库的多次查询变为一次
        List<PmsCategory> selectList = this.baseMapper.selectList(null);

        //1、查出所有分类
        //1、1）查出所有一级分类
        List<PmsCategory> level1Categorys = getParent_cid(selectList, 0L);

        //封装数据
        Map<String, List<Catelog2Vo>> parentCid = level1Categorys.stream().collect(Collectors.toMap(k -> k.getCatId().toString(), v -> {
            //1、每一个的一级分类,查到这个一级分类的二级分类
            List<PmsCategory> categoryEntities = getParent_cid(selectList, v.getCatId());

            //2、封装上面的结果
            List<Catelog2Vo> catelog2Vos = null;
            if (categoryEntities != null) {
                catelog2Vos = categoryEntities.stream().map(l2 -> {
                    Catelog2Vo catelog2Vo = new Catelog2Vo(v.getCatId().toString(), null, l2.getCatId().toString(), l2.getName().toString());

                    //1、找当前二级分类的三级分类封装成vo
                    List<PmsCategory> level3Catelog = getParent_cid(selectList, l2.getCatId());

                    if (level3Catelog != null) {
                        List<Catelog2Vo.Category3Vo> category3Vos = level3Catelog.stream().map(l3 -> {
                            //2、封装成指定格式
                            Catelog2Vo.Category3Vo category3Vo = new Catelog2Vo.Category3Vo(l2.getCatId().toString(), l3.getCatId().toString(), l3.getName());

                            return category3Vo;
                        }).collect(Collectors.toList());
                        catelog2Vo.setCatalog3List(category3Vos);
                    }

                    return catelog2Vo;
                }).collect(Collectors.toList());
            }
            return catelog2Vos;
        }));

        return parentCid;
    }


    private List<PmsCategory> getParent_cid(List<PmsCategory> selectList,Long parentCid) {
        List<PmsCategory> categoryEntities = selectList.stream().filter(item -> item.getParentCid().equals(parentCid)).collect(Collectors.toList());
        return categoryEntities;
    }
}
